﻿// Copyright: 2012
// Author: Minh Vu - YoungJ
// File: XmlAction.cs - PhoneAppRssReader - PhoneAppRssReader
// Time: 9:21 PM 04/18/2012

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Xml.Linq;
using PhoneAppRssReader.Entity;

namespace PhoneAppRssReader.Utls
{
    public class XmlAction
    {
        private const string _fileData = "data.xml";

        /// <summary>
        /// Save rss feed to the Isolated Storage
        /// </summary>
        /// <param name="feed">a rss feed</param>
        /// <returns>True if success</returns>
        public static bool SaveFeed(Feed feed)
        {
            try
            {
                using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    XDocument xdoc;
                    var xeleFeed = new XElement("rss",
                                                new XAttribute("id", feed.Id),
                                                new XAttribute("title", feed.Title),
                                                new XAttribute("url", feed.Url.UrlEncode()));

                    if (!storageFile.FileExists(_fileData))
                    {
                        //create xml and save to xml
                        using (var stream = new IsolatedStorageFileStream(_fileData, FileMode.Create, storageFile))
                        {
                            xdoc = new XDocument(new XDeclaration("1.0", "utf-8", ""),
                                                 new XElement("root", xeleFeed));
                            xdoc.Save(stream);
                            return true;
                        }
                    }

                    //load data from xml
                    using (var stream = new IsolatedStorageFileStream(_fileData, FileMode.Open, storageFile))
                    {
                        xdoc = XDocument.Load(stream);
                    }

                    var root = xdoc.Element("root");
                    if (root == null) return false;

                    if (root.ToString().Equals("<root />"))
                    {
                        root.Add(xeleFeed);
                    }
                    else
                    {
                        var rsses = root.Descendants("rss");

                        var last = rsses.Last();
                        last.AddAfterSelf(xeleFeed);
                    }
                    //save data to xml
                    using (var stream = new IsolatedStorageFileStream(_fileData, FileMode.Create, storageFile))
                    {
                        xdoc.Save(stream);
                        return true;
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Add: " + ex.Message);
                return false;
            }
        }

        public static bool EditFeed(Feed updateFeed)
        {
            try
            {
                using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    if (!storageFile.FileExists(_fileData)) return false;
                    XDocument xdoc;
                    using (var stream = new IsolatedStorageFileStream(_fileData, FileMode.Open, storageFile))
                    {
                        xdoc = XDocument.Load(stream);
                    }
                    var root = xdoc.Element("root");
                    if (root == null) return false;


                    var eleRss = root.Descendants("rss")
                        .FirstOrDefault(
                            c => ((string)c.Attribute("id"))
                                     .Equals(updateFeed.Id.ToString(CultureInfo.InvariantCulture)));

                    if (eleRss == null) return false;
                    eleRss.SetAttributeValue("title", updateFeed.Title);
                    if (!eleRss.getValue("url").UrlDecode().Equals(updateFeed.Url))
                    {
                        DeleteRssSource(updateFeed.Id);
                        eleRss.SetAttributeValue("url", updateFeed.Url.UrlEncode());
                    }

                    using (var stream = new IsolatedStorageFileStream(_fileData, FileMode.Create, storageFile))
                    {
                        xdoc.Save(stream);
                        return true;
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Edit: " + ex.Message);
                return false;
            }
        }


        public static bool DeleteFeed(int feedId)
        {
            try
            {
                using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    if (!storageFile.FileExists(_fileData)) return false;
                    XDocument xdoc;
                    using (var stream = new IsolatedStorageFileStream(_fileData, FileMode.Open, storageFile))
                    {
                        xdoc = XDocument.Load(stream);
                    }
                    var root = xdoc.Element("root");
                    if (root == null) return false;


                    var eleRss = root.Descendants("rss")
                        .FirstOrDefault(
                            c => ((string)c.Attribute("id"))
                                     .Equals(feedId.ToString(CultureInfo.InvariantCulture)));

                    if (eleRss == null) return false;
                    eleRss.Remove();

                    using (var stream = new IsolatedStorageFileStream(_fileData, FileMode.Create, storageFile))
                    {
                        xdoc.Save(stream);
                        return true;
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Edit: " + ex.Message);
                return false;
            }
        }
        /// <summary>
        /// Add list rss feed to Isolated storage
        /// </summary>
        /// <param name="feeds">List rss Feed</param>
        /// <returns>TRUE if success</returns>
        public static bool SaveFeed(ObservableCollection<Feed> feeds)
        {
            try
            {
                using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    XDocument xdoc;
                    var id = NextId();
                    var xeleFeeds =
                        feeds.Select(
                            feed =>
                            new XElement("rss", new XAttribute("id", id++), new XAttribute("title", feed.Title),
                                         new XAttribute("url", feed.Url.UrlEncode())));


                    if (!storageFile.FileExists(_fileData))
                    {
                        //create xml and save to xml
                        using (var stream = new IsolatedStorageFileStream(_fileData, FileMode.Create, storageFile))
                        {
                            xdoc = new XDocument(new XDeclaration("1.0", "utf-8", ""),
                                                 new XElement("root", xeleFeeds));
                            xdoc.Save(stream);
                            return true;
                        }
                    }

                    //load data from xml
                    using (var stream = new IsolatedStorageFileStream(_fileData, FileMode.Open, storageFile))
                    {
                        xdoc = XDocument.Load(stream);
                    }

                    var root = xdoc.Element("root");
                    if (root == null) return false;


                    var rsses = root.Descendants("rss");
                    var last = rsses.Last();
                    last.AddAfterSelf(xeleFeeds);
                    //save data to xml
                    using (var stream = new IsolatedStorageFileStream(_fileData, FileMode.Create, storageFile))
                    {
                        xdoc.Save(stream);
                        return true;
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Add: " + ex.Message);
                return false;
            }
        }

        public static int NextId()
        {
            try
            {
                using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    if (!storageFile.FileExists(_fileData)) return 1;

                    using (var stream = new IsolatedStorageFileStream(_fileData, FileMode.Open, storageFile))
                    {
                        var xdoc = XDocument.Load(stream);

                        var root = xdoc.Element("root");
                        if (root == null || root.ToString().Equals("<root />")) return 1;

                        var rsses = root.Descendants("rss");
                        var last = rsses.Last();

                        var nextId = Convert.ToInt16(last.getValue("id")) + 1;
                        return nextId;
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("NextId: " + ex.Message);
                return -1;
            }

        }

        public static IEnumerable<Feed> Read()
        {
            using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (!storageFile.FileExists(_fileData)) return null;
                using (var stream = new IsolatedStorageFileStream(_fileData, FileMode.Open, storageFile))
                {
                    try
                    {
                        var xdoc = XDocument.Load(stream);
                        var root = xdoc.Element("root");
                        if (root == null) return null;
                        var result = from r in root.Descendants("rss")
                                     select new Feed
                                     {
                                         Id = Convert.ToInt16(r.getValue("id")),
                                         Title = r.getValue("title"),
                                         Url = r.getValue("url").UrlDecode()
                                     };
                        return result;
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("Read: " + ex.Message);
                        return null;
                    }

                }
            }

        }

        public static bool SaveRssFeedWeb(int id, string xml)
        {
            try
            {
                var xdoc = XDocument.Parse(xml);
                var filename = id + ".xml";
                using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    /*
                     *  if exist file, compare publish date of rss feed, if equals, delete the old file
                     */
                    if (storageFile.FileExists(filename))
                    {
                        var oldDate = GetPublishDateRssSource(ReadRssSource(filename));
                        var newDate = GetPublishDateRssSource(xml);

                        if (newDate.CompareTo(oldDate) <= 0)
                            return true;

                        storageFile.DeleteFile(filename);

                    }

                    using (var stream = new IsolatedStorageFileStream(filename, FileMode.Create, storageFile))
                    {
                        xdoc.Save(stream);
                        return true;
                    }
                }

            }
            catch (Exception ex)
            {
                Debug.WriteLine("Save rss feed: " + ex.Message);
                return false;
            }
        }

        public static DateTime GetPublishDateRssSource(string xml)
        {
            try
            {
                var root = XElement.Parse(xml);
                var strPubDate = root.Descendants("pubDate").First().Value;
                return DateTime.Parse(strPubDate);
            }
            catch (Exception)
            {
                return DateTime.Now.AddDays(-7);
            }
        }

        public static string ReadRssSource(string filename)
        {
            using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (!storageFile.FileExists(filename)) return null;
                using (var stream = new IsolatedStorageFileStream(filename, FileMode.Open, storageFile))
                {
                    return XDocument.Load(stream).ToString();
                }
            }

        }

        public static bool DeleteRssSource(int feedId)
        {
            var filename = feedId + ".xml";
            using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (storageFile.FileExists(filename))
                {
                    storageFile.DeleteFile(filename);
                    return true;
                }
            }
            return false;
        }

    }
}